From 6c683972499ed435c9a782ba3f706016691d5ec1 Mon Sep 17 00:00:00 2001 From: Peter Keresztes Schmidt Date: Sun, 6 Jun 2021 16:38:02 +0200 Subject: [PATCH 1/2] Time: Convert some timeval operations to std::chrono Also remove now defunct timeval helper methods. --- src/CMakeLists.txt | 1 - src/zm_event.cpp | 4 +- src/zm_monitorstream.cpp | 29 ++++---- src/zm_rtp_source.cpp | 27 +++++--- src/zm_time.cpp | 22 ------- src/zm_time.h | 139 ++------------------------------------- 6 files changed, 41 insertions(+), 181 deletions(-) delete mode 100644 src/zm_time.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 82f6cefe0..4e8224db2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -60,7 +60,6 @@ set(ZM_BIN_SRC_FILES zm_signal.cpp zm_stream.cpp zm_swscale.cpp - zm_time.cpp zm_user.cpp zm_utils.cpp zm_videostore.cpp diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 32cb95f76..b9b5f3925 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -238,7 +238,7 @@ Event::~Event() { gettimeofday(&end_time, nullptr); } - std::chrono::duration delta_time = + FPSeconds delta_time = zm::chrono::duration_cast(end_time) - zm::chrono::duration_cast(start_time); Debug(2, "start_time: %" PRIi64 ".% " PRIi64 " end_time: %" PRIi64 ".%" PRIi64, static_cast(start_time.tv_sec), @@ -580,7 +580,7 @@ void Event::AddFrame( or ( monitor_state == Monitor::PREALARM ); if (db_frame) { - std::chrono::duration delta_time = + FPSeconds delta_time = zm::chrono::duration_cast(timestamp) - zm::chrono::duration_cast(start_time); Debug(1, "Frame delta is %" PRIi64 ".%" PRIi64 " - %" PRIi64 ".%" PRIi64 " = %.2f, score %u zone_stats.size %zu", static_cast(start_time.tv_sec), static_cast(start_time.tv_usec), diff --git a/src/zm_monitorstream.cpp b/src/zm_monitorstream.cpp index a9fead28b..99cc01720 100644 --- a/src/zm_monitorstream.cpp +++ b/src/zm_monitorstream.cpp @@ -347,8 +347,7 @@ bool MonitorStream::sendFrame(const char *filepath, const timeval ×tamp) { } // Calculate how long it takes to actually send the frame - struct timeval frameStartTime; - gettimeofday(&frameStartTime, nullptr); + 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", @@ -363,13 +362,14 @@ bool MonitorStream::sendFrame(const char *filepath, const timeval ×tamp) { fputs("\r\n", stdout); fflush(stdout); - struct timeval frameEndTime; - gettimeofday(&frameEndTime, nullptr); + TimePoint send_end_time = std::chrono::steady_clock::now(); + Milliseconds frame_send_time = std::chrono::duration_cast(send_end_time - send_start_time); - int frameSendTime = tvDiffMsec(frameStartTime, frameEndTime); - if ( frameSendTime > 1000/maxfps ) { + if (frame_send_time > Milliseconds(lround(Milliseconds::period::den / maxfps))) { maxfps /= 2; - Info("Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps); + Info("Frame send time %" PRIi64 " msec too slow, throttling maxfps to %.2f", + static_cast(frame_send_time.count()), + maxfps); } last_frame_sent = TV_2_FLOAT(now); @@ -408,8 +408,7 @@ bool MonitorStream::sendFrame(Image *image, const timeval ×tamp) { unsigned char *img_buffer = temp_img_buffer; // Calculate how long it takes to actually send the frame - struct timeval frameStartTime; - gettimeofday(&frameStartTime, nullptr); + TimePoint send_start_time = std::chrono::steady_clock::now(); switch ( type ) { case STREAM_JPEG : @@ -451,14 +450,14 @@ bool MonitorStream::sendFrame(Image *image, const timeval ×tamp) { fputs("\r\n", stdout); fflush(stdout); - struct timeval frameEndTime; - gettimeofday(&frameEndTime, nullptr); + TimePoint send_end_time = std::chrono::steady_clock::now(); + Milliseconds frame_send_time = std::chrono::duration_cast(send_end_time - send_start_time); - int frameSendTime = tvDiffMsec(frameStartTime, frameEndTime); - if ( frameSendTime > 1000/maxfps ) { + if (frame_send_time > Milliseconds(lround(Milliseconds::period::den / maxfps))) { maxfps /= 1.5; - Warning("Frame send time %d msec too slow, throttling maxfps to %.2f", - frameSendTime, maxfps); + Warning("Frame send time %" PRIi64 " msec too slow, throttling maxfps to %.2f", + static_cast(frame_send_time.count()), + maxfps); } } // Not mpeg last_frame_sent = TV_2_FLOAT(now); diff --git a/src/zm_rtp_source.cpp b/src/zm_rtp_source.cpp index 2fd5bc41b..0d9330f8e 100644 --- a/src/zm_rtp_source.cpp +++ b/src/zm_rtp_source.cpp @@ -67,11 +67,11 @@ RtpSource::RtpSource( mRtpFactor = mRtpClock; mBaseTimeReal = tvNow(); - mBaseTimeNtp = tvZero(); + mBaseTimeNtp = {}; mBaseTimeRtp = rtpTime; - mLastSrTimeReal = tvZero(); - mLastSrTimeNtp = tvZero(); + mLastSrTimeReal = {}; + mLastSrTimeNtp = {}; mLastSrTimeRtp = 0; if ( mCodecId != AV_CODEC_ID_H264 && mCodecId != AV_CODEC_ID_MPEG4 ) @@ -160,12 +160,18 @@ bool RtpSource::updateSeq(uint16_t seq) { void RtpSource::updateJitter( const RtpDataHeader *header ) { if ( mRtpFactor > 0 ) { - uint32_t localTimeRtp = mBaseTimeRtp + uint32_t(tvDiffSec(mBaseTimeReal) * mRtpFactor); + timeval now = {}; + gettimeofday(&now, nullptr); + + FPSeconds time_diff = + zm::chrono::duration_cast(now) - zm::chrono::duration_cast(mBaseTimeReal); + + uint32_t localTimeRtp = mBaseTimeRtp + static_cast(time_diff.count() * mRtpFactor); uint32_t packetTransit = localTimeRtp - ntohl(header->timestampN); Debug(5, "Delta rtp = %.6f\n Local RTP time = %x Packet RTP time = %x Packet transit RTP time = %x", - tvDiffSec(mBaseTimeReal), + time_diff.count(), localTimeRtp, ntohl(header->timestampN), packetTransit); @@ -190,7 +196,8 @@ void RtpSource::updateRtcpData( uint32_t ntpTimeSecs, uint32_t ntpTimeFrac, uint32_t rtpTime) { - struct timeval ntpTime = tvMake(ntpTimeSecs, suseconds_t((USEC_PER_SEC*(ntpTimeFrac>>16))/(1<<16))); + timeval ntpTime = zm::chrono::duration_cast( + Seconds(ntpTimeSecs) + Microseconds((Microseconds::period::den * (ntpTimeFrac >> 16)) / (1 << 16))); Debug(5, "ntpTime: %ld.%06ld, rtpTime: %x", ntpTime.tv_sec, ntpTime.tv_usec, rtpTime); @@ -204,12 +211,14 @@ void RtpSource::updateRtcpData( mLastSrTimeNtp.tv_sec, mLastSrTimeNtp.tv_usec, rtpTime, ntpTime.tv_sec, ntpTime.tv_usec, rtpTime); - double diffNtpTime = tvDiffSec( mBaseTimeNtp, ntpTime ); + FPSeconds diffNtpTime = + zm::chrono::duration_cast(ntpTime) - zm::chrono::duration_cast(mBaseTimeNtp); + uint32_t diffRtpTime = rtpTime - mBaseTimeRtp; - mRtpFactor = (uint32_t)(diffRtpTime / diffNtpTime); + mRtpFactor = static_cast(diffRtpTime / diffNtpTime.count()); Debug( 5, "NTP-diff: %.6f RTP-diff: %d RTPfactor: %d", - diffNtpTime, diffRtpTime, mRtpFactor); + diffNtpTime.count(), diffRtpTime, mRtpFactor); } mLastSrTimeNtpSecs = ntpTimeSecs; mLastSrTimeNtpFrac = ntpTimeFrac; diff --git a/src/zm_time.cpp b/src/zm_time.cpp deleted file mode 100644 index 417ee2b2b..000000000 --- a/src/zm_time.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// -// ZoneMinder Time Functions & Definitions Implementation, $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. -// - -#include "zm_time.h" - -// Blank diff --git a/src/zm_time.h b/src/zm_time.h index c5e7fe75e..d263dfb41 100644 --- a/src/zm_time.h +++ b/src/zm_time.h @@ -20,7 +20,6 @@ #ifndef ZM_TIME_H #define ZM_TIME_H -#include "zm_logger.h" #include #include @@ -51,137 +50,10 @@ struct DeltaTimeval #define DT_MAXGRAN DT_GRAN_1000000 -#define USEC_PER_SEC 1000000 -#define MSEC_PER_SEC 1000 - -/* -extern struct timeval tv; -*/ - -inline int tvDiffUsec( struct timeval first, struct timeval last ) -{ - return( (last.tv_sec - first.tv_sec) * USEC_PER_SEC) + ((USEC_PER_SEC + last.tv_usec - first.tv_usec) - USEC_PER_SEC ); -} - -inline int tvDiffUsec( struct timeval first ) -{ - struct timeval now; - gettimeofday( &now, nullptr ); - return( tvDiffUsec( first, now ) ); -} - -inline int tvDiffMsec( struct timeval first, struct timeval last ) -{ - return( (last.tv_sec - first.tv_sec) * MSEC_PER_SEC) + (((MSEC_PER_SEC + last.tv_usec - first.tv_usec) / MSEC_PER_SEC) - MSEC_PER_SEC ); -} - -inline int tvDiffMsec( struct timeval first ) -{ - struct timeval now; - gettimeofday( &now, nullptr ); - return( tvDiffMsec( first, now ) ); -} - -inline double tvDiffSec( struct timeval first, struct timeval last ) -{ - return( double(last.tv_sec - first.tv_sec) + double(((USEC_PER_SEC + last.tv_usec - first.tv_usec) - USEC_PER_SEC) / (1.0*USEC_PER_SEC) ) ); -} - -inline double tvDiffSec( struct timeval first ) -{ - struct timeval now; - gettimeofday( &now, nullptr ); - return( tvDiffSec( first, now ) ); -} - -inline struct timeval tvZero() -{ - struct timeval t = { 0, 0 }; - return( t ); -} - -inline int tvIsZero( const struct timeval t ) -{ - return( t.tv_sec == 0 && t.tv_usec == 0 ); -} - -inline int tvCmp( struct timeval t1, struct timeval t2 ) -{ - if ( t1.tv_sec < t2.tv_sec ) - return( -1 ); - if ( t1.tv_sec > t2.tv_sec ) - return( 1 ); - if ( t1.tv_usec < t2.tv_usec ) - return( -1 ); - if ( t1.tv_usec > t2.tv_usec ) - return( 1 ); - return( 0 ); -} - -inline int tvEq( struct timeval t1, struct timeval t2 ) -{ - return( t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec ); -} - -inline struct timeval tvNow( void ) -{ - struct timeval t; - gettimeofday( &t, nullptr ); - return( t ); -} - -inline struct timeval tvCheck( struct timeval &t ) -{ - if ( t.tv_usec >= USEC_PER_SEC ) - { - Warning( "Timestamp too large %ld.%ld\n", t.tv_sec, (long int) t.tv_usec ); - t.tv_sec += t.tv_usec / USEC_PER_SEC; - t.tv_usec %= USEC_PER_SEC; - } - else if ( t.tv_usec < 0 ) - { - Warning( "Got negative timestamp %ld.%ld\n", t.tv_sec, (long int)t.tv_usec ); - t.tv_usec = 0; - } - return( t ); -} - -// Add t2 to t1 -inline struct timeval tvAdd( struct timeval t1, struct timeval t2 ) -{ - tvCheck(t1); - tvCheck(t2); - t1.tv_sec += t2.tv_sec; - t1.tv_usec += t2.tv_usec; - if ( t1.tv_usec >= USEC_PER_SEC ) - { - t1.tv_sec++; - t1.tv_usec -= USEC_PER_SEC; - } - return( t1 ); -} - -// Subtract t2 from t1 -inline struct timeval tvSub( struct timeval t1, struct timeval t2 ) -{ - tvCheck(t1); - tvCheck(t2); - t1.tv_sec -= t2.tv_sec; - t1.tv_usec -= t2.tv_usec; - if ( t1.tv_usec < 0 ) - { - t1.tv_sec--; - t1.tv_usec += USEC_PER_SEC; - } - return( t1 ) ; -} - -inline struct timeval tvMake( time_t sec, suseconds_t usec ) -{ - struct timeval t; - t.tv_sec = sec; - t.tv_usec = usec; - return( t ); +inline struct timeval tvNow() { + timeval t = {}; + gettimeofday(&t, nullptr); + return t; } typedef std::chrono::microseconds Microseconds; @@ -190,6 +62,9 @@ typedef std::chrono::seconds Seconds; typedef std::chrono::minutes Minutes; typedef std::chrono::hours Hours; +// floating point seconds +typedef std::chrono::duration FPSeconds; + typedef std::chrono::steady_clock::time_point TimePoint; typedef std::chrono::system_clock::time_point SystemTimePoint; From d8d27bcc92b276022cdb2490cdecddc5db70f05b Mon Sep 17 00:00:00 2001 From: Peter Keresztes Schmidt Date: Mon, 7 Jun 2021 23:47:47 +0200 Subject: [PATCH 2/2] Time: Replace remaining DeltaTimeval usage with std::chrono --- src/zm_event.cpp | 22 ++++++------------- src/zm_frame.cpp | 2 +- src/zm_frame.h | 4 ++-- src/zm_monitor.cpp | 8 +++---- src/zm_time.h | 55 ---------------------------------------------- 5 files changed, 14 insertions(+), 77 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index b9b5f3925..b77ba43e9 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -454,14 +454,12 @@ void Event::WriteDbFrames() { while (frame_data.size()) { Frame *frame = frame_data.front(); frame_data.pop(); - frame_insert_sql += stringtf("\n( %" 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); + frame_insert_sql += stringtf("\n( %" PRIu64 ", %d, '%s', from_unixtime( %ld ), %.2f, %d ),", + id, frame->frame_id, + frame_type_names[frame->type], + frame->timestamp.tv_sec, + std::chrono::duration_cast(frame->delta).count(), + frame->score); if (config.record_event_stats and frame->zone_stats.size()) { for (ZoneStats &stats : frame->zone_stats) { stats_insert_sql += stringtf("\n(%" PRIu64 ",%d,%u,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%u),", @@ -591,13 +589,7 @@ void Event::AddFrame( Milliseconds delta_time_ms = std::chrono::duration_cast(delta_time); // The idea is to write out 1/sec - frame_data.push(new Frame(id, - frames, - frame_type, - timestamp, - zm::chrono::duration_cast(delta_time_ms), - score, - zone_stats)); + frame_data.push(new Frame(id, frames, frame_type, timestamp, delta_time_ms, score, zone_stats)); double fps = monitor->get_capture_fps(); if (write_to_db or diff --git a/src/zm_frame.cpp b/src/zm_frame.cpp index 79873efd0..2b28a62b1 100644 --- a/src/zm_frame.cpp +++ b/src/zm_frame.cpp @@ -4,7 +4,7 @@ Frame::Frame(event_id_t p_event_id, int p_frame_id, FrameType p_type, struct timeval p_timestamp, - const DeltaTimeval &p_delta, + Milliseconds p_delta, int p_score, std::vector p_stats) : event_id(p_event_id), diff --git a/src/zm_frame.h b/src/zm_frame.h index 05f49791c..87769711b 100644 --- a/src/zm_frame.h +++ b/src/zm_frame.h @@ -42,7 +42,7 @@ class Frame { int p_frame_id, FrameType p_type, struct timeval p_timestamp, - const DeltaTimeval &p_delta, + Milliseconds p_delta, int p_score, std::vector p_stats ); @@ -51,7 +51,7 @@ class Frame { int frame_id; FrameType type; struct timeval timestamp; - struct DeltaTimeval delta; + Milliseconds delta; int score; std::vector zone_stats; }; diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 74093859e..d79afbe21 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -484,8 +484,8 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) { /* "AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS," */ analysis_fps_limit = dbrow[col] ? strtod(dbrow[col], nullptr) : 0.0; col++; analysis_update_delay = strtoul(dbrow[col++], nullptr, 0); - capture_delay = (dbrow[col] && atof(dbrow[col])>0.0)?int(DT_PREC_6/atof(dbrow[col])):0; col++; - alarm_capture_delay = (dbrow[col] && atof(dbrow[col])>0.0)?int(DT_PREC_6/atof(dbrow[col])):0; col++; + capture_delay = (dbrow[col] && atof(dbrow[col]) > 0.0) ? int(Microseconds::period::den / atof(dbrow[col])) : 0; col++; + alarm_capture_delay = (dbrow[col] && atof(dbrow[col]) > 0.0) ? int(Microseconds::period::den / atof(dbrow[col])) : 0; col++; /* "Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, " // V4L Settings */ device = dbrow[col] ? dbrow[col] : ""; col++; @@ -2963,8 +2963,8 @@ bool Monitor::DumpSettings(char *output, bool verbose) { sprintf(output+strlen(output), "Alarm Frame Count : %d\n", alarm_frame_count ); sprintf(output+strlen(output), "Section Length : %d\n", section_length); sprintf(output+strlen(output), "Min Section Length : %d\n", min_section_length); - sprintf(output+strlen(output), "Maximum FPS : %.2f\n", capture_delay?(double)DT_PREC_3/capture_delay:0.0); - sprintf(output+strlen(output), "Alarm Maximum FPS : %.2f\n", alarm_capture_delay?(double)DT_PREC_3/alarm_capture_delay:0.0); + sprintf(output+strlen(output), "Maximum FPS : %.2f\n", capture_delay ? (double) Microseconds::period::den / capture_delay : 0.0); + sprintf(output+strlen(output), "Alarm Maximum FPS : %.2f\n", alarm_capture_delay ? (double) Microseconds::period::den / alarm_capture_delay : 0.0); sprintf(output+strlen(output), "Reference Blend %%ge : %d\n", ref_blend_perc); sprintf(output+strlen(output), "Alarm Reference Blend %%ge : %d\n", alarm_ref_blend_perc); sprintf(output+strlen(output), "Track Motion : %d\n", track_motion); diff --git a/src/zm_time.h b/src/zm_time.h index d263dfb41..0df20345a 100644 --- a/src/zm_time.h +++ b/src/zm_time.h @@ -23,33 +23,6 @@ #include #include -// Structure used for storing the results of the subtraction -// of one struct timeval from another - -struct DeltaTimeval -{ - bool positive; - unsigned long delta; - unsigned long sec; - unsigned long fsec; - unsigned long prec; -}; - -#define DT_GRAN_1000000 1000000 -#define DT_PREC_6 DT_GRAN_1000000 -#define DT_GRAN_100000 100000 -#define DT_PREC_5 DT_GRAN_100000 -#define DT_GRAN_10000 10000 -#define DT_PREC_4 DT_GRAN_10000 -#define DT_GRAN_1000 1000 -#define DT_PREC_3 DT_GRAN_1000 -#define DT_GRAN_100 100 -#define DT_PREC_2 DT_GRAN_100 -#define DT_GRAN_10 10 -#define DT_PREC_1 DT_GRAN_10 - -#define DT_MAXGRAN DT_GRAN_1000000 - inline struct timeval tvNow() { timeval t = {}; gettimeofday(&t, nullptr); @@ -99,27 +72,6 @@ struct posix_duration_cast> { ); } }; - -// chrono -> DeltaTimeval caster -template -struct posix_duration_cast, DeltaTimeval> { - template - static DeltaTimeval cast(std::chrono::duration const &d) { - typedef std::chrono::duration> fsec_t; - DeltaTimeval res = {}; - - Seconds secs = std::chrono::duration_cast(d); - fsec_t fsec = std::chrono::duration_cast>(d - secs); - - res.positive = fsec >= Seconds::zero(); - res.delta = abs((secs + fsec).count()); - res.sec = secs.count(); - res.fsec = fsec.count(); - res.prec = Prec; - - return res; - } -}; } // chrono -> timeval @@ -134,13 +86,6 @@ template Duration duration_cast(timeval const &tv) { return impl::posix_duration_cast::cast(tv); } - -// chrono -> DeltaTimeval -template -auto duration_cast(std::chrono::duration const &d) --> typename std::enable_if::value, DeltaTimeval>::type { - return impl::posix_duration_cast, DeltaTimeval>::template cast(d); -} } }